// Copyright 2019 Conflux Foundation. All rights reserved.
// Conflux is free software and distributed under GNU General Public License.
// See http://www.gnu.org/licenses/

use crate::{
    executive::{
        contract_address, ExecutionOutcome, Executive, InternalContractMap,
        TransactOptions,
    },
    machine::Machine,
    state::State,
    verification::{compute_receipts_root, compute_transaction_root},
    vm::{CreateContractAddress, Env},
};
use cfx_bytes::Bytes;
use cfx_internal_common::debug::ComputeEpochDebugRecord;
use cfx_parameters::{
    consensus::{GENESIS_GAS_LIMIT, ONE_CFX_IN_DRIP},
    consensus_internal::{
        GENESIS_TOKEN_COUNT_IN_CFX, TWO_YEAR_UNLOCK_TOKEN_COUNT_IN_CFX,
    },
};
use cfx_state::{state_trait::*, CleanupMode};
use cfx_statedb::{Result as DbResult, StateDb};
use cfx_storage::{StorageManager, StorageManagerTrait};
use cfx_types::{address_util::AddressUtil, Address, U256};
use keylib::KeyPair;
use primitives::{
    storage::STORAGE_LAYOUT_REGULAR_V0, Action, Block, BlockHeaderBuilder,
    BlockReceipts, SignedTransaction, Transaction,
};
use rustc_hex::FromHex;
use secret_store::SecretStore;
use std::{
    collections::HashMap,
    fs::File,
    io::{BufRead, BufReader, Read},
    sync::Arc,
};
use toml::Value;

pub const DEV_GENESIS_PRI_KEY: &'static str =
    "46b9e861b63d3509c88b7817275a30d22d62c8cd8fa6486ddee35ef0d8e0495f";
/// Used in Ethereum replay e2e test.
pub const DEV_GENESIS_PRI_KEY_2: &'static str =
    "9a6d3ba2b0c7514b16a006ee605055d71b9edfad183aeb2d9790e9d4ccced471";
pub const GENESIS_TRANSACTION_DATA_STR: &'static str = "
The Times 28/Oct/2020 Fees for current accounts as negative rates loom";

pub const GENESIS_TRANSACTION_CREATE_CREATE2FACTORY: &'static str = "608060405234801561001057600080fd5b506102a2806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c806390184b021461003b5780639c4ae2d014610075575b600080fd5b6100616004803603602081101561005157600080fd5b50356001600160a01b0316610139565b604080519115158252519081900360200190f35b61011d6004803603604081101561008b57600080fd5b8101906020810181356401000000008111156100a657600080fd5b8201836020820111156100b857600080fd5b803590602001918460018302840111640100000000831117156100da57600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295505091359250610157915050565b604080516001600160a01b039092168252519081900360200190f35b6001600160a01b031660009081526020819052604090205460ff1690565b600080600060019050838551602087016000f59150813b610176575060005b806101c8576040805162461bcd60e51b815260206004820152600e60248201527f63726561746532206661696c6564000000000000000000000000000000000000604482015290519081900360640190fd5b6001600160a01b03821660009081526020819052604090205460ff16156102205760405162461bcd60e51b815260040180806020018281038252602181526020018061024d6021913960400191505060405180910390fd5b506001600160a01b0381166000908152602081905260409020805460ff1916600117905590509291505056fe636f6e747261637420686173206265656e206465706c6f796564206265666f7265a265627a7a723158200af37f6335cc41d7dfae2771f8663b4a48fc54c11ec8a28682901a0951f9ce5364736f6c634300050b0032";
pub const GENESIS_TRANSACTION_CREATE_GENESIS_TOKEN_MANAGER_TWO_YEAR_UNLOCK:
    &'static str = "60806040526040516109f33803806109f38339818101604052610f0081101561002757600080fd5b50604080516078808252610f208201909252610300830191610600840191610900850191610c0086019160609160208201610f008038833901905050905060005b60188110156100f15786816018811061007d57fe5b60200201516001826018811061008f57fe5b6005020160000180546001600160a01b0319166001600160a01b03929092169190911790558681601881106100c057fe5b60200201518282815181106100d157fe5b6001600160a01b0390921660209283029190910190910152600101610068565b5060005b60188110156101815785816018811061010a57fe5b60200201516001826018811061011c57fe5b6005020160010180546001600160a01b0319166001600160a01b039290921691909117905585816018811061014d57fe5b602002015182826018018151811061016157fe5b6001600160a01b03909216602092830291909101909101526001016100f5565b5060005b60188110156102145784816018811061019a57fe5b6020020151600182601881106101ac57fe5b6005020160020180546001600160a01b0319166001600160a01b03929092169190911790558481601881106101dd57fe5b60200201518282601860020201815181106101f457fe5b6001600160a01b0390921660209283029190910190910152600101610185565b5060005b60188110156102a75783816018811061022d57fe5b60200201516001826018811061023f57fe5b6005020160030180546001600160a01b0319166001600160a01b039290921691909117905583816018811061027057fe5b602002015182826018600302018151811061028757fe5b6001600160a01b0390921660209283029190910190910152600101610218565b5060005b601881101561033a578281601881106102c057fe5b6020020151600182601881106102d257fe5b6005020160040180546001600160a01b0319166001600160a01b039290921691909117905582816018811061030357fe5b602002015182826018600402018151811061031a57fe5b6001600160a01b03909216602092830291909101909101526001016102ab565b5060005b60188110156103d45760005b60058110156103985760006079836018811061036257fe5b60050201826005811061037157fe5b0180546001600160a01b0319166001600160a01b039290921691909117905560010161034a565b50600060f182601881106103a857fe5b602081049091018054921515601f9092166101000a91820260ff9092021990921617905560010161033e565b50600060f281905580546001600160a01b03191673088800000000000000000000000000000000000117905530316801158e460913d00000808210156104175750805b9081900390674563918244f40000808310156104305750815b60008054604080517f3e3e64280000000000000000000000000000000000000000000000000000000081523060048201526611c37937e080006024820152905195849003956001600160a01b0390921692633e3e6428928592604480820193929182900301818588803b1580156104a657600080fd5b505af11580156104ba573d6000803e3d6000fd5b505060008054604080517fe66c1bea00000000000000000000000000000000000000000000000000000000815230600482015290516001600160a01b03909216955063e66c1bea9450879350602480820193929182900301818588803b15801561052357600080fd5b505af1158015610537573d6000803e3d6000fd5b5050600080546040517f10128d3e0000000000000000000000000000000000000000000000000000000081526020600482018181528b5160248401528b516001600160a01b0390941697506310128d3e96508b95509384936044909301928287019202908190849084905b838110156105ba5781810151838201526020016105a2565b5050505090500192505050600060405180830381600087803b1580156105df57600080fd5b505af11580156105f3573d6000803e3d6000fd5b505050601830310460f355506103d8985088975061061b9650600095505050505050396000f3fe608060405234801561001057600080fd5b50600436106100725760003560e01c8063d4c66d1f11610050578063d4c66d1f146100ef578063f58ac2c714610112578063febe49091461011a57610072565b80631fb40c9a146100775780632e1a7d4d146100b6578063438739ce146100d5575b600080fd5b61009a6004803603604081101561008d57600080fd5b5080359060200135610146565b604080516001600160a01b039092168252519081900360200190f35b6100d3600480360360208110156100cc57600080fd5b503561018f565b005b6100dd61029e565b60408051918252519081900360200190f35b61009a6004803603604081101561010557600080fd5b50803590602001356102a4565b6100dd6102cc565b6100d36004803603604081101561013057600080fd5b50803590602001356001600160a01b03166102d2565b60006018831080156101585750600582105b61016157600080fd5b6079836018811061016e57fe5b60050201826005811061017d57fe5b01546001600160a01b03169392505050565b6018811061019c57600080fd5b60f181601881106101a957fe5b602081049091015460ff601f9092166101000a900416156101c957600080fd5b6000805b60058110156102135733607984601881106101e457fe5b6005020182600581106101f357fe5b01546001600160a01b0316141561020b576001820191505b6001016101cd565b50600381101561022257600080fd5b600160f1836018811061023157fe5b602081049091018054921515601f9092166101000a91820260ff9092021990921617905560f28054600101908190556018141561026b5733ff5b60f354604051339180156108fc02916000818181858888f19350505050158015610299573d6000803e3d6000fd5b505050565b60f25490565b60006018831080156102b65750600582105b6102bf57600080fd5b6001836018811061016e57fe5b60f35490565b601882106102df57600080fd5b60f182601881106102ec57fe5b602081049091015460ff601f9092166101000a9004161561030c57600080fd5b60005b600581101561029957336001846018811061032657fe5b60050201826005811061033557fe5b01546001600160a01b0316141561039b57816079846018811061035457fe5b60050201826005811061036357fe5b0180547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b03929092169190911790555b60010161030f56fea265627a7a7231582031e74a9262e6be7e9bf29a815b1e0805013b7e99a5ebf15cc550eb13331a73ac64736f6c634300050b00320000000000000000000000001c39346b71c62fe1e0fa0dfd811874da8886d0da000000000000000000000000196b5c7aa64f5c07acaa18eb7b0e23e6a656d91d00000000000000000000000012d01852e9efd6b276b396f9c429b5ea2ce68d7b000000000000000000000000161a48c2c6f0dc7e3dc0851e69ca24c899e6a92c0000000000000000000000001e8166512eb1104813cf83a2cd691cd175fe7d2300000000000000000000000019aa9ffba4f82f268aa323c400026af04aa01eb1000000000000000000000000173516a951aa2c78633078c28d38f94956c6657d0000000000000000000000001d0e69a89c53b8e14dcb233a1967226a9059cd8b0000000000000000000000001bef1ee33d2b5d7615deefe62aa759c4b8613dac000000000000000000000000109f0e5fbcc0922c47389d29e474aa01be0bac9f00000000000000000000000012899262a059d939ad57a163896689799340dc8f000000000000000000000000116569adda77821078fde258bae9f8cd5d3b88b20000000000000000000000001198e0db134d74942ee32a45e7d0c1ac131f159a00000000000000000000000017471a6279f1f751f5879cf8cb70e87f927e229e00000000000000000000000018c6e3015e6c0aa91eec5f035ab7f6c216e9ef7900000000000000000000000013e5e6227866c504b34cbf8ca06ffadf4d00edde000000000000000000000000107b6577fd039ad2f1e17c00fd63f073869384160000000000000000000000001aab50bba72bdbd5b9cd3699a0a62e8e071298e10000000000000000000000001f10a4699594c3613cdde79b8bf595faca3625dc0000000000000000000000001c25cb36e03cdadfa9187eb080ce666b75e51d5e0000000000000000000000001c79a3bd1abb8270e234c79a7f6fe010f83b0299000000000000000000000000139c5dd1b717e36dead9a7127d8332a2ca18072000000000000000000000000018af70ad24ad99a1b2562d2a003bd977a0ad67ee000000000000000000000000195037a194c1737b748dd1be6d798ca16fc226dc0000000000000000000000001a95ca87d3f14f2508c73fb6c58076b6ca076b89000000000000000000000000197ef49a99577a837f736cdd54dede8501c246240000000000000000000000001f122a863a6ebf85dea83b7374b6a371acad89b3000000000000000000000000176104f80f2365ebbcf32464f1a061e5c6685f95000000000000000000000000145893c9619d59f50e900bb64906d6f2a8ab4bce00000000000000000000000013cb788a261951d85f057d986f095146a65428b6000000000000000000000000174ddde4b7abbea1b5e9b41336c7dd3b78ad56b8000000000000000000000000125923402428859180fff679d8b980d5a4a1cae50000000000000000000000001fe1bf743857ae50b69abb28e5bcb22da3bba5c1000000000000000000000000179e85296442bdccd3c2bf0f3e19cc4db974323d0000000000000000000000001cadfcd2b099f0284dafb952a720948827ff3bd1000000000000000000000000168243843fad0237d802019efd2d0b481a969c8f0000000000000000000000001f49276d028d7d307f48b2ba53b677b7c9b11bd600000000000000000000000013a66170ce359000e9ef152ee35fd5646052f16a0000000000000000000000001c74342709b1b96abfe8fd920c737b901c6192850000000000000000000000001daa1b73da40b6d9e31cef7c386bab2384c1a57d00000000000000000000000017769de226792c3258d5f7efe96aa37b2538c2180000000000000000000000001eaf228c6eefb2ac35839df7692efb09388faf17000000000000000000000000173beec769acf96e795ebdfb4a2ef9cf59816ea3000000000000000000000000124cf9f5b24087444da8ff2164eeb11d217eff080000000000000000000000001a4110634e7aa71a3db5cce3b7fd1b0b4f9044990000000000000000000000001f2c4ffec8bb9624ceac71db4ea77527a09fdd860000000000000000000000001b9ddff474813e050af1707d080797da6204a7ed0000000000000000000000001fc3e32dd509c396467d33b658f3c89080967d920000000000000000000000001ddae9e09df8feafe8995d6c695712e29e6e28c70000000000000000000000001954ebd8190a317806e9eb850d81ab8013bc5f870000000000000000000000001748f28ac045745900397dc234041a12d9db33430000000000000000000000001ed3c805c7ceaadb0dba857b6f2fb1353e27b0a50000000000000000000000001465b700cd37d496354000c44c9db690a32e67d10000000000000000000000001cd3dae2a60ada3761517bcd54eaeb9bad5c269e000000000000000000000000158ac43a6e9ccee9a9bceadcbfd38a010b0c6753000000000000000000000000129c7d6ace0a4668840daa28dd30d7e9e32583950000000000000000000000001fb679f589f0b9bebc6e564baf065114a84a2d310000000000000000000000001432931f9af35c731b99fca9075fa0e5a0699a2f00000000000000000000000017ac05421be349b90985c9eccbdacf178797f42b00000000000000000000000011e5f6eca6e7396e56f011f559ff802a9b4edcbc00000000000000000000000017271951589b1132e02b260598e758ea5d38e0b20000000000000000000000001e4eaf2edbd10f71590d21717f65ff3d39a5348f0000000000000000000000001d4e16a5f5ef26e4efcd91e5ad302b85057008970000000000000000000000001de5e4147ab8d4b6737007f9d2c518b1026b0fb00000000000000000000000001e79a2e53d7ffb3fdc5456d45e8e902877c1d9e1000000000000000000000000174bb6d49946c3741ea24d5b1b81215f7f2480000000000000000000000000001abf441fc688a3c3531ac2a3d08e706f774878ce0000000000000000000000001f45b5f43a66ce54b7dd5e6fde0cd63dad00821b00000000000000000000000011e2affbfc280d1ad866cd031fafea873d61f7e100000000000000000000000012689d0f68dfac4bb1395523c3f6cc491b9ea8e0000000000000000000000000112f326f35d4bf0557f9782a195991d9ed45f60100000000000000000000000010cb3d899e9a1d609c260f0d616c1622cab631c80000000000000000000000001ec00f0eb987bec2a76c34209d51c9e10611811a0000000000000000000000001513558ac522f0663d8871f803455266b02bde600000000000000000000000001e068d88ebc1627739866de0108b3ee4649178e9000000000000000000000000154f589a716a76348ed5d688ed2f9337ef828f270000000000000000000000001985e0c97c1c6b4672e2b8141256b884096d802700000000000000000000000010aa1ff8e269b8597cc30b739694e00e946680e200000000000000000000000017c00cae2fa0009035bcb078b821bd53da9f79890000000000000000000000001e519402892147b7aec6cf3dec6c35fdbf1042f40000000000000000000000001eb621b98e22c15c426c5cbcf6e96e4d1266233c0000000000000000000000001955118fb69c67031078b939a23d28350576b2f2000000000000000000000000145e91766cd70fd9ade4cf462cfcee909d7334f9000000000000000000000000102abd262039aebe21a94bee6d7d75347b0e23f000000000000000000000000012ae1fafaaa92a043d5ddb6780ed97f79a19a0e70000000000000000000000001228727ca01c586fd3f9d4138b52c848b4e1a6f20000000000000000000000001afe27743317c9465b7fdcfe1b68518e53b96d7b00000000000000000000000011409fce8056171a9805e24f9408157a97a56dc000000000000000000000000011d18265a6fed6192ee58d731611f8ad4b3840f70000000000000000000000001d62ab16d0223e34f5d06e260e12001664776d330000000000000000000000001e9f1c041c10970897dc1fcfd4c4bbf66a222dc20000000000000000000000001d02dd4f8594eb53c1862e24b46aa444c8457e990000000000000000000000001bd74451f8c8eefa00782f03e5b03607468155c50000000000000000000000001bd6d1ef4a5589fe458c1379875ed481e244c83300000000000000000000000015a6b96c1fd21a023ba389b4a4b97fa653497ca20000000000000000000000001a718474ceeceed276dcd8acdef5c81962cef9c500000000000000000000000014e1d0600081142fb1cf51f91511ffb16a01e81a000000000000000000000000142ce2b0bfea9bf247e664faa2d8b2e8a25cc1190000000000000000000000001fa39e565b6f089025327580d8d8b87951e99f1800000000000000000000000015456001b4d5ccc620e74fb79df16df7812262190000000000000000000000001cb75d4237ccc0c82133b0b0d7bcd48fab0010d70000000000000000000000001bc44976a1fa7dbfb2de60d8f6de3714a40884e200000000000000000000000019f052d42bcb3df1b99beee870135e91dc05f22e0000000000000000000000001b0f7fb09baba34fb58ee25de08c6eb0855413fa000000000000000000000000100185147a447a3f7cad09cff9dda2d8b6d2a4330000000000000000000000001703abb9f3442381c050236762678aa37b9852fb000000000000000000000000110e7b4fe0c4fe24ac8927e11905655f2393fd7500000000000000000000000014c1181752c9ce5f3c8e1abdd582508c43908da30000000000000000000000001b123ca70d5fe971f512d00be1bd446f2249015e000000000000000000000000173a9e9ddf7200aee8af31d621104dd4273dbeae00000000000000000000000010618e897aad58caa8a2b6c62271cd9db6153da10000000000000000000000001a35bc9a6df7515ab5d7ed41f08b93eccfbce25d0000000000000000000000001c616aefe8912b398d817da1cf4b11b508b1e9080000000000000000000000001e0593fd9d0ac58de9c7688d35fcc153c5b6ba4800000000000000000000000015de6173a1e586fb67b6af318dc2b03d61cc50fe00000000000000000000000012c0de1e81ca2bef7ec67ecc236f53549026881e0000000000000000000000001875d4b9319349191508cef1a718a3dda02fe64a0000000000000000000000001004a1ba742552f3fface4df43b3d991110efcd60000000000000000000000001b081ab58592675f8ff4773151332ac9f8cb1b0d000000000000000000000000115ebf99eac02c748541e411e73be677260d0337";
pub const GENESIS_TRANSACTION_CREATE_GENESIS_TOKEN_MANAGER_FOUR_YEAR_UNLOCK:
    &'static str = "6080604052604051610a4b380380610a4b8339818101604052611e0081101561002757600080fd5b506040805160f1808252611e408201909252610600830191610c0084019161120085019161180086019160609160208201611e208038833901905050905060005b60308110156100f15786816030811061007d57fe5b60200201516001826030811061008f57fe5b6005020160000180546001600160a01b0319166001600160a01b03929092169190911790558681603081106100c057fe5b60200201518282815181106100d157fe5b6001600160a01b0390921660209283029190910190910152600101610068565b5060005b60308110156101815785816030811061010a57fe5b60200201516001826030811061011c57fe5b6005020160010180546001600160a01b0319166001600160a01b039290921691909117905585816030811061014d57fe5b602002015182826030018151811061016157fe5b6001600160a01b03909216602092830291909101909101526001016100f5565b5060005b60308110156102145784816030811061019a57fe5b6020020151600182603081106101ac57fe5b6005020160020180546001600160a01b0319166001600160a01b03929092169190911790558481603081106101dd57fe5b60200201518282603060020201815181106101f457fe5b6001600160a01b0390921660209283029190910190910152600101610185565b5060005b60308110156102a75783816030811061022d57fe5b60200201516001826030811061023f57fe5b6005020160030180546001600160a01b0319166001600160a01b039290921691909117905583816030811061027057fe5b602002015182826030600302018151811061028757fe5b6001600160a01b0390921660209283029190910190910152600101610218565b5060005b603081101561033a578281603081106102c057fe5b6020020151600182603081106102d257fe5b6005020160040180546001600160a01b0319166001600160a01b039290921691909117905582816030811061030357fe5b602002015182826030600402018151811061031a57fe5b6001600160a01b03909216602092830291909101909101526001016102ab565b5073162788589c8e386863f217faef78840919fb28548160306005028151811061036057fe5b6001600160a01b039092166020928302919091019091015260005b60308110156104125760005b60058110156103d557600060f1836030811061039f57fe5b6005020182600581106103ae57fe5b0180546001600160a01b0319166001600160a01b0392909216919091179055600101610387565b5060006101e182603081106103e657fe5b602081049091018054921515601f9092166101000a91820260ff9092021990921617905560010161037b565b5060006101e381905580546001600160a01b03191673088800000000000000000000000000000000000117905530316801158e460913d00000808210156104565750805b9081900390674563918244f400008083101561046f5750815b60008054604080517f3e3e64280000000000000000000000000000000000000000000000000000000081523060048201526611c37937e080006024820152905195849003956001600160a01b0390921692633e3e6428928592604480820193929182900301818588803b1580156104e557600080fd5b505af11580156104f9573d6000803e3d6000fd5b505060008054604080517fe66c1bea00000000000000000000000000000000000000000000000000000000815230600482015290516001600160a01b03909216955063e66c1bea9450879350602480820193929182900301818588803b15801561056257600080fd5b505af1158015610576573d6000803e3d6000fd5b5050600080546040517f10128d3e0000000000000000000000000000000000000000000000000000000081526020600482018181528b5160248401528b516001600160a01b0390941697506310128d3e96508b95509384936044909301928287019202908190849084905b838110156105f95781810151838201526020016105e1565b5050505090500192505050600060405180830381600087803b15801561061e57600080fd5b505af1158015610632573d6000803e3d6000fd5b50505060303031046101e455506103f0985088975061065b9650600095505050505050396000f3fe608060405234801561001057600080fd5b50600436106100725760003560e01c8063d4c66d1f11610050578063d4c66d1f146100ef578063f58ac2c714610112578063febe49091461011a57610072565b80631fb40c9a146100775780632e1a7d4d146100b6578063438739ce146100d5575b600080fd5b61009a6004803603604081101561008d57600080fd5b5080359060200135610146565b604080516001600160a01b039092168252519081900360200190f35b6100d3600480360360208110156100cc57600080fd5b503561018f565b005b6100dd6102a2565b60408051918252519081900360200190f35b61009a6004803603604081101561010557600080fd5b50803590602001356102a9565b6100dd6102d1565b6100d36004803603604081101561013057600080fd5b50803590602001356001600160a01b03166102d8565b60006030831080156101585750600582105b61016157600080fd5b60f1836030811061016e57fe5b60050201826005811061017d57fe5b01546001600160a01b03169392505050565b6030811061019c57600080fd5b6101e181603081106101aa57fe5b602081049091015460ff601f9092166101000a900416156101ca57600080fd5b6000805b6005811015610214573360f184603081106101e557fe5b6005020182600581106101f457fe5b01546001600160a01b0316141561020c576001820191505b6001016101ce565b50600381101561022357600080fd5b60016101e1836030811061023357fe5b602081049091018054921515601f9092166101000a91820260ff909202199092161790556101e38054600101908190556030141561026e5733ff5b6101e454604051339180156108fc02916000818181858888f1935050505015801561029d573d6000803e3d6000fd5b505050565b6101e35490565b60006030831080156102bb5750600582105b6102c457600080fd5b6001836030811061016e57fe5b6101e45490565b6030821080156102ed575043826249d4000211155b6102f657600080fd5b6101e1826030811061030457fe5b602081049091015460ff601f9092166101000a9004161561032457600080fd5b60005b600581101561029d57336001846030811061033e57fe5b60050201826005811061034d57fe5b01546001600160a01b031614156103b3578160f1846030811061036c57fe5b60050201826005811061037b57fe5b0180547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b03929092169190911790555b60010161032756fea265627a7a723158203a011234f7721df8ae4eb6080c990594b95fa442f511cf10238e6886fb2869a764736f6c634300050b00320000000000000000000000001a1b3ee08767c02e8cc83f675d3f0048113a7cf4000000000000000000000000169c5caea1d3ae87cfe048b40a591d2008bdef020000000000000000000000001ea06b092810443987279980615ee6c6c1533d2100000000000000000000000010d6d8610eff580747eebe7a57548fbda7535ba50000000000000000000000001fa472b91a52400b7833e7fa1fba87a03ab414970000000000000000000000001da039774f732633edf3bb7996ebbafcee7adff400000000000000000000000011d881d7dc23c1406278ca5784a4bc4e368e30220000000000000000000000001ffdec160b96eb19e613084954f1ad8a1448899e00000000000000000000000010dd4d2b170df885eb18a9954bfa4b01fde9dc750000000000000000000000001e1fd29e50522f295c6217b2f1ebaa18b8f768aa000000000000000000000000187e239af70ae909af7083b2144b00e9006c12870000000000000000000000001eb648fe61f34059293f7cfb5d9e772a8ca9eed700000000000000000000000011c8503b48e9ea288f4c7c579dfae64f290d23510000000000000000000000001bdcc3ec554847600f9a176f2c92cbf3d26807cd00000000000000000000000018e4d95d9f47a086b28684c8005735637e87b4e300000000000000000000000013f3099c506cded49c04e69b0219d5d56584288a0000000000000000000000001683322aa3be7aa4f8ec96316f19fbba130927eb000000000000000000000000196cc6f28159c2340ab5bea7ca59303a12201d3700000000000000000000000013b2e190dcfffaa7a529c46d7d54075b519db68e0000000000000000000000001b70c38e447a92f2b3ec507ddb1ad2fc75f3d1b1000000000000000000000000161ab0dbe63b67cfd73555d33428a4c5f04349ee00000000000000000000000011ae3ec102352b45a0cce66a6fecd7dec8a6186f000000000000000000000000112cbb8c28592a34e957744e0d67a18ba968aef40000000000000000000000001749d1fcc93988ae53415de08234faba371130f50000000000000000000000001f77cb93851a9de1115d4e79a026542bdf583d410000000000000000000000001c39e84c343fbadc99cae7e2458e87cf1c0f4b230000000000000000000000001cbb0f3a211974235e5da078beeefe0e9241ee8800000000000000000000000011a8e63c02aeb016b85426fd25cd0330c8d8044e0000000000000000000000001712a8a4c9e5d43c1bb3e932d9825e2a95a7b19c00000000000000000000000014481d7e85f0a40dce2cadf1931590407e409948000000000000000000000000176cf492df54908850366c1661d293ce2d1906ae0000000000000000000000001aa89de36c8a70d8dd0146940f55ecf7040bfd1600000000000000000000000012ae836e98b2e7ccd2400418fa49193747c06f86000000000000000000000000174836431f8a8b5652427054783091146cccd4880000000000000000000000001d857e34225e289ada33c54f894404134b3d8fc600000000000000000000000011650fdaf66331e251a153c3fb2ee3c1d5978f550000000000000000000000001d8bf76d6bd48ad7c019628776f1938d8560bfb5000000000000000000000000180ad53d595924184c4ef21506d6435305ae036700000000000000000000000011da627925c7d582d7c867b93316836965664944000000000000000000000000169578f33db19f8f4a509a3ead02e4138df0711f0000000000000000000000001f44f8afbe76bd3428aede4136408aa59d87e3350000000000000000000000001d4422da38a8728cce209c72054e026a5475879700000000000000000000000011a87d7f68bb021447021bb8e92b90b79afa4f0300000000000000000000000015718055431b57b4e763d0e665501ce9d9840d4a000000000000000000000000124efa09247d9ce95d0d87f2c63a06753b10935d0000000000000000000000001a1576c5e212d435fdbc708451cbc56acea123d100000000000000000000000017961bda87798583d3bea2fb94d8a55410e94a5d000000000000000000000000114f31834e1ed406319c5d9347d8facb058f1a7700000000000000000000000015f20c8ab611f7aaa08c3d7a68d6a1a96e0a843600000000000000000000000017159a91cb764c582d0190f5d8585a3c0fac435b00000000000000000000000014bac71dd6c85ae9aa79754958cdeaeb01ab7bdd0000000000000000000000001478e59335f706efbc66b33f3fd6ac22be367fa100000000000000000000000015908009baa55f8b1f63d4aeed49199ab7c4fcba000000000000000000000000120085ba3dfb867372dc60777c0339cf4b12cb6800000000000000000000000016e48245e15fc004d013128d33448118fbe913c8000000000000000000000000173c79de7bb7ae3009896731108e07d65920753e000000000000000000000000197a3ebf9ed97090c8f8ad4e562c020edd1169a50000000000000000000000001f08570bdf857faf744dcbe32692774ba4fbb9b20000000000000000000000001571eb406035c23eff4dee23a2e89531d314ac1e00000000000000000000000019981211d84becf958c648cdbd049562db32639600000000000000000000000010d6f9dbc3de7bed2ae77420867be1246509335c0000000000000000000000001ef4320a7ad6bca87d9a8eee7fee48c3ce3dd04400000000000000000000000016cce23fb8d19f6b34a62500bd0c7c1821ee57600000000000000000000000001bb9b4d7ec9e419b204cd3348716c5860cd69dc0000000000000000000000000108b89b4f457216a069c39ec41dc6885bc3d87750000000000000000000000001850c8ec46a64c1be04be4765e838a0d426a926a000000000000000000000000167dcb6be21303eba8f132b8f0c05622335b3d0e0000000000000000000000001822b294fa950c30b500d9040dc53d08d1ae31e10000000000000000000000001807adb9d0355460a3685ab1f2431edcf734b6a0000000000000000000000000187b27120d1746de5ebabc5cebf71a78ba73d58d0000000000000000000000001c919fa0254630d3c601d0b549c320b5d263aae60000000000000000000000001a026e53db2924109a6cddd691b75103e7ce706a0000000000000000000000001494ca43465fb961c6336d3c95d218e0b4c627de0000000000000000000000001f8d20c3a180609b176ca31a23dada1ca0b2a59600000000000000000000000016556f82e1f61eeec52ce195a89872b249cb65f30000000000000000000000001f72332820a9e6adccddbe49d63aa5f705d42c9500000000000000000000000017c880e9395d75dc8e5b60899321eff65104dc6c00000000000000000000000013eaeb425ce275e3d395d9451da56e1cd5aea76c0000000000000000000000001aa60e6336d9b0aa22cf15a46d5945b8dc5046f10000000000000000000000001fb60a3bde07b63809158c19bd4e2fc51a0de3b00000000000000000000000001278e9f25a2f9fea91d5bf82110135e5fd18dabe0000000000000000000000001c7e2d019ee41c95bca77b33f31569fd2328e22300000000000000000000000012ede54e04b75d4bc49fa05e7b53edea54e0cbbe000000000000000000000000142c9de1b4bff6291ef74e3c52994856a48c2d560000000000000000000000001738eabf08182883279521ad7cdb358410c399e30000000000000000000000001bd19d58735a8febe3f6d3823bc0f9035ca30de30000000000000000000000001ecbad4800a7ba6bb6fd3311bdf1c4068f420e740000000000000000000000001fd10494a4a6c1f0ec9a6fa47629fcf7955cc77b0000000000000000000000001386048f6a8a22a2f56286bacb19cfdeef09514a00000000000000000000000019a9ff915024eb668afc4a10737ee2c6d9d41eef0000000000000000000000001fa3ca0b8c39b09257bb0c9c92440f2767cbd9c500000000000000000000000018c302a0d662f562a128cada42334533e1e1aa1d0000000000000000000000001c2af8e51b495778c150a8cbd4950470f7674a8f000000000000000000000000142d6008948ca645317876c9b2de5fcd2bb4f19700000000000000000000000019573e8cc43e5116f889a6ef9cdb9b17c6347c760000000000000000000000001bedae7a60958e50d3cb284717ed435b65bb259a0000000000000000000000001e51c7d219612f052200ed7b780c5ec954dc60b500000000000000000000000018fcc6a3dd7ea49c905aab894bd4090aed47d0980000000000000000000000001bb6b9e40cbd5749c2dbc57de96f54949e93d7130000000000000000000000001fa07e756a474e08170e4e97fb95dfe3cb0080370000000000000000000000001ec1341c7386fce388291efa841b9faccb9256140000000000000000000000001a357a297e703b0379b97e593a60437ee14230e200000000000000000000000011331b1010edd47109faef514c4ea121ff1a56a8000000000000000000000000115baa7a81edea5ebd53c180611af84215a2e7d3000000000000000000000000113c96ef8cdc918c8c6c1f33127fdffc6ec2f9f9000000000000000000000000105d52af2e13d71452897cadf5f5b4a1c3424f7b0000000000000000000000001c6c36a1a192ab6ea5c6870ddf81e93879bc4d610000000000000000000000001eebb002658794d12dd9165f267b7c9a6e5a77d30000000000000000000000001b06ca409dfbd2175c6409f7914cdadf8f53564200000000000000000000000018684f4c35983230082d700d0fd2c6433037ede50000000000000000000000001367fa246313c7d82288dfef799b6e847e319eaa0000000000000000000000001ffa8b1cfbac65a90a1c4fb5e6386a8eec4a8162000000000000000000000000174b4809b5d783ff68f435b3e5d75db377fafa740000000000000000000000001d81b5fb88d5725647a06fd5583e473840b332370000000000000000000000001d4b217346301fa751bd1044520553ea8e9d0a7e00000000000000000000000018aed7eac0f509c004411890492c146574aecc100000000000000000000000001aa58c3896708fcf577c1c6041d52c8349c1330b0000000000000000000000001dd158e54893e5ed5ac0826527e3b74f6c5cc2770000000000000000000000001bb8d626c20d985de5274d8e3c723074249c7411000000000000000000000000128f24fbbc02c06687ec325b90196ae2bddc7a9c0000000000000000000000001971812cf895996bc7441daf12fddfb20da428f90000000000000000000000001bf4a896674ef090aecb402b40aba7f99172d85d0000000000000000000000001fc9f962de60665991756455e8d86ccff9bfa50a000000000000000000000000106264367cb824db8c4a0f9c4fe7dae667e4f2dd0000000000000000000000001797fd220385af22995d98c2be9ce0019320b06e0000000000000000000000001d8a54d1221ab997a090fb9a6d3e2ccb7810da4c0000000000000000000000001e5325377cfcdab2062b71c615f5042f32682cda0000000000000000000000001d95cff7bc50de9c15fc71b5ede26cccec0cb3e500000000000000000000000017095132e4aced82f085c0383c05b9fd01e778d50000000000000000000000001fb7087eb73eedac71b6bc2df05c311e490b349a00000000000000000000000013ae8266e2e0fbdde4836cfdecafe0aa843b64fb0000000000000000000000001747859696fcdd4c86ca55d37c9b2021452cda65000000000000000000000000169f126b0664616791eda4eb337ce2964345144e000000000000000000000000107207e56f8e393d2f5b9f79bfd1ee5279c157500000000000000000000000001374cb956d7085e577db1c90909dbef9fee2add50000000000000000000000001ca61a200d1e759b791b118f05dac05ade1b30e40000000000000000000000001895533b1ff791c069c0bf3ff4c5b221f57b4a6000000000000000000000000014b18604539d8ce5b601494c23e16b42a1195c9b0000000000000000000000001e523cc03b119698f4f8c9afadd19cc544031232000000000000000000000000157a5182e6883ba067bc4a48ba97476ae18ae586000000000000000000000000172dd48124f4935afbd62828f01b9d7045a3b5e60000000000000000000000001c16ff1f3a9b7e0c953d27f0df1a7d7be4bff54f000000000000000000000000134c352a43e4ffa8adaf15c040004621d64e4441000000000000000000000000120f42d4b477a449f4dda728a45f4da8090d70950000000000000000000000001aae583b23f993fb90280c83bc99de0fceae43b900000000000000000000000017ab81f2c6d11312ad53e2d2b74b35ef1bc9d2c1000000000000000000000000151796552dcf88f932bf206815e8b4d01f7a513600000000000000000000000013681bea09525fe9516d4f8bd752a648eb112b400000000000000000000000001be7f3f60346f187e33931c58dc081e35dba54050000000000000000000000001947e443d1ecb97f24f7ad327a5480435f7e977400000000000000000000000011ad012fdcfcfa9ee0a4dec6dd85c8921a3e5b310000000000000000000000001a1b727274ddb74307154ba8cc0ce3128de6915e0000000000000000000000001fccbc46f552540d5954de4aaf23150231258bb00000000000000000000000001089d6403f9a3e9d442d27b7f48661e4719bf7910000000000000000000000001cc5d9fb63fcf33967301e735b4f463cdee025190000000000000000000000001c3dadb1431455b0b17c3ec3452b58379ed3e227000000000000000000000000173036e813284fa7cf1e941a7d8bb58d572563220000000000000000000000001fc0c8f8fad51d091ede8255aaa2ffbf13726ed0000000000000000000000000162eecb8fc4492dc25a4103cbdef9c7a00ebe7c3000000000000000000000000199e9c9f0f6f885c737851feccad67c2332dd68100000000000000000000000012550c7632e480e9e1ccb4cbd0eac77f01bb5167000000000000000000000000136866bccd3e9d37f60be823b9771c160da2bc3400000000000000000000000015f74f68a19706abc8c7e1d557cb1794597975ce0000000000000000000000001fb34f46cb02b197e9a816b0796c5b7c07460af5000000000000000000000000175b0e0d0dfb0b894b34547e91e19de88b164c350000000000000000000000001cf9fbb02f76e9d9dcf3dd7e9ea79a3951b8d9a400000000000000000000000010fda3815f931568b50d27b51bee4d628173200f000000000000000000000000147ba3bde789eadaeafdbfd950e9e47c192683f7000000000000000000000000171afd37faca4424bb92ce0663ea07681bb7952c0000000000000000000000001b06b034349046d9b1a3996b94b063db544fd2ab00000000000000000000000018b9ba06e00cebc7e004a0f7dcb350e7a10588660000000000000000000000001cc55604826be10d3fbe8684ceca1b9009a1fdc8000000000000000000000000120368ba7f711fbf83859b0626cbf338562e8c3c00000000000000000000000012de73339e87b769a47be28129237f1bb51c6dda0000000000000000000000001675080eeaf02aa3f42e2ce0088134c15700f97800000000000000000000000017b7a43e5a5056c0c1fc7de9bc9a2222a5e7b6aa000000000000000000000000181450c39d67153f8f1122b3e3cfc32f2804dad70000000000000000000000001a7cb561da7b2ca2486b6216731378fa93db1fd500000000000000000000000017a78d53fbb3c6e45439eabc376098e9dc14e561000000000000000000000000120baba874f15dfaf72199c4569431079170b395000000000000000000000000111ea3a66e660b19e4a49b86443fcf338cea7b56000000000000000000000000156fd874d3e4a04d758c08c83d4f90327da89cf30000000000000000000000001e8b7883192cfcb28413555cb5a2e0b2a9b79c8d00000000000000000000000010400d94199a3d396133af3e7831dbca486125d800000000000000000000000017b8361a0a9800ddb482b72b695dff42600e04470000000000000000000000001de8c274c91b2037dc2b616efa54ab16c6d3d967000000000000000000000000143d3d16b1b8c7ea1284d19e03c33971e808c8cc0000000000000000000000001ce97c3645cd92044360169fb3aa6b18938bd41f00000000000000000000000016493cb838aa29e8ce9285049ce018d063b5fc2d00000000000000000000000018333beb0fe8b68959d94118d913a2dc15299637000000000000000000000000163e94e4c52808ab6a15bd5a5d6e5d543842af880000000000000000000000001cc163514b560b6a63e82afd8147eb70b9adbb85000000000000000000000000108b8b1333523a79ac363d8f41805e81b085d55d00000000000000000000000011df294a2a3d39d771292544814f03fc7fa0372500000000000000000000000017eb6b5ca175a517fa2b57b47655be8ad4ff0bf300000000000000000000000012c9d04552a55e6da35678aabc261913cb2e09f6000000000000000000000000142e644053a3a06df9619a66fe211ab408e5ff4500000000000000000000000014147970c48f269ef7d1a617e1338e86aa8ec1d80000000000000000000000001baec050e060376134d29fc789f15a1e33ad9bd10000000000000000000000001206ae8e8335e762c824f47d574fc1170314fe1b00000000000000000000000019b6f0929e7fd3660be7af695a86a1b1bcae32980000000000000000000000001637bf08d9ec89aff3e9bb5b5a901b38a1b553ee00000000000000000000000013a650982df87caefca4b062346752485a9c2b2600000000000000000000000016494fb4c54fc3248c28cdbdfca47310581c98f00000000000000000000000001770ae7335e7ff3ebcf50d31b0e8d7568be3eff20000000000000000000000001e1724be1dbc115dcae8a2e931a666bac1ce37c90000000000000000000000001174e1afadb9779b10ee3aa99895649f2f19ff1e000000000000000000000000163f51d2ffca11bf505bb477a60b78288b8118bd0000000000000000000000001aa293f4e72b332fa0e54e1e0cb208ca7edf49e50000000000000000000000001712c9d548dd73baad4a12e1cb63962f6861d1bc00000000000000000000000014ec6f8f283c84102bbe10b03fb7819be124281a0000000000000000000000001589c0b10d1d4cb8943ad3099233410c750e85eb0000000000000000000000001fea5ebdd7d330efeddc18f92a9a98502e4ff6e300000000000000000000000016dc17f50895718e183f00c2e8310ddb9e055d2d00000000000000000000000014372aba2b87190350ae07ee39b55453352eac62000000000000000000000000156fd92b8e5830227fe308333e23385903f517c70000000000000000000000001c783766bc850c4c3ed6d669a421c312d218523d000000000000000000000000182fd1a72b3e5d7e5017e366a51f48f728a0bda400000000000000000000000013a6f6b30a198981294c3200d7adac311061bcbb000000000000000000000000136f709f4f5aa27fdfe9d1d105246e7024ded50a0000000000000000000000001ec55fe04d50144a8f60c6ccf7b522700908d2940000000000000000000000001cfe1e073e950a863a5fc2bf5a7043c85da1e3b6000000000000000000000000193a91d9f22d41904b54eacd675098fb6975d48f00000000000000000000000016b7ac29d8bb4dd740551db1e3736cd9fcc7c0250000000000000000000000001ed98ffc9a1c853181ff1608e59bfe18046193910000000000000000000000001764d12851a794733f9899d2455f0eb9612c7ac1000000000000000000000000115c213810356002782175399a0bee0c8f68307c000000000000000000000000133873a6e92e2e8f54025c23355aff0657703e25000000000000000000000000166f6c7c81c93c5935225d155a590a10a4d0a3f80000000000000000000000001222a450ba9f6096c6d1f779395a74e2249f90f20000000000000000000000001aeb6a24854d2a1036ad003292042abd6d6409fe0000000000000000000000001c7739185c82cfaf454c28727317eb69ad702b4d0000000000000000000000001a743be42c662a09ed1f79a17b8a1381b599cbb400000000000000000000000013c16d65828361da26a024fd9d802430424302ea0000000000000000000000001ae685a3bd12ddad85e52bb35161440b3e026f4d0000000000000000000000001e9437c55c5de73124e4805fe99d2efbaae493cc0000000000000000000000001c2a41da5cbdff2d5a91a97ecb18cb68435ed542000000000000000000000000118fb6713eeba26c9f1e0d5a1d17321ca102e2d600000000000000000000000014a13b115f47393606ba3f5a210a83b55709ee2300000000000000000000000012a63f34f44f3d59cd9600691155a2e78530cb7e";
pub const GENESIS_TRANSACTION_CREATE_FUND_POOL: &'static str = "6080604052604051610475380380610475833981810160405260a081101561002657600080fd5b5060005b60058110156100ab5781816005811061003f57fe5b60200201516001826005811061005157fe5b0180546001600160a01b0319166001600160a01b039290921691909117905560006006826005811061007f57fe5b602081049091018054921515601f9092166101000a91820260ff9092021990921617905560010161002a565b505060008080556009556103b1806100c46000396000f3fe6080604052600436106100345760003560e01c8063c65df79414610036578063e9c857cf1461007c578063f3fef3a314610091575b005b34801561004257600080fd5b506100606004803603602081101561005957600080fd5b50356100ca565b604080516001600160a01b039092168252519081900360200190f35b34801561008857600080fd5b506100606100f7565b34801561009d57600080fd5b50610034600480360360408110156100b457600080fd5b506001600160a01b038135169060200135610106565b6000600582106100d957600080fd5b600182600581106100e657fe5b01546001600160a01b031692915050565b6007546001600160a01b031690565b30318082111561011557600080fd5b600080805b600581101561015657336001826005811061013157fe5b01546001600160a01b0316141561014e5760019250809150610156565b60010161011a565b508161016157600080fd5b6000546101d5576001600981905560008190556007805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0388161790556008859055600682600581106101ae57fe5b602091828204019190066101000a81548160ff021916908315150217905550505050610378565b6007546001600160a01b0386811691161415806101f457508360085414155b156102825760005b60058110156102405760006006826005811061021457fe5b602081049091018054921515601f9092166101000a91820260ff909202199092161790556001016101fc565b50600160098190556007805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0388161790556008859055600682600581106101ae57fe5b6006816005811061028f57fe5b602081049091015460ff601f9092166101000a9004166102e257600980546001908101909155600682600581106102c257fe5b602091828204019190066101000a81548160ff0219169083151502179055505b60036009541061037457600060098190558080555b600581101561033b5760006006826005811061030f57fe5b602081049091018054921515601f9092166101000a91820260ff909202199092161790556001016102f7565b506040516001600160a01b0386169085156108fc029086906000818181858888f19350505050158015610372573d6000803e3d6000fd5b505b5050505b505056fea265627a7a72315820188ae3ff8c03ae58077bbb43f7c8ac7be42840fbf66adf8cc93d6a6c2e68ce9964736f6c634300050b00320000000000000000000000001ee83f2a2668d364fac640512e9133547856544f0000000000000000000000001bb74df3b833e13709e39d778c6a7234d32b033f0000000000000000000000001a4ee88d74f6e7147baabaa21d411da429fb6f970000000000000000000000001910e0c34cc4093825e07d846b9c596a7325387800000000000000000000000017dd6ffde9ec6b20d7ec28d2ad26be64df68fe34";

pub const GENESIS_ACCOUNT_ADDRESS_STR: &'static str =
    "1949000000000000000000000000000000001001";

lazy_static! {
    pub static ref DEV_GENESIS_KEY_PAIR: KeyPair =
        KeyPair::from_secret(DEV_GENESIS_PRI_KEY.parse().unwrap()).unwrap();
    pub static ref DEV_GENESIS_KEY_PAIR_2: KeyPair =
        KeyPair::from_secret(DEV_GENESIS_PRI_KEY_2.parse().unwrap()).unwrap();
}

pub fn default(dev_or_test_mode: bool) -> HashMap<Address, U256> {
    if !dev_or_test_mode {
        return HashMap::new();
    }
    let mut accounts: HashMap<Address, U256> = HashMap::new();
    // FIXME: Decide the genesis initialization for mainnet.
    let balance = U256::from_dec_str("5000000000000000000000000000000000")
        .expect("Not overflow"); // 5*10^33
    accounts.insert(DEV_GENESIS_KEY_PAIR.address(), balance);
    accounts.insert(DEV_GENESIS_KEY_PAIR_2.address(), balance);
    accounts
}

pub fn load_secrets_file(
    path: &String, secret_store: &SecretStore,
) -> Result<HashMap<Address, U256>, String> {
    let file = File::open(path)
        .map_err(|e| format!("failed to open file: {:?}", e))?;
    let buffered = BufReader::new(file);

    let mut accounts: HashMap<Address, U256> = HashMap::new();
    let balance =
        U256::from_dec_str("10000000000000000000000").map_err(|e| {
            format!(
                "failed to parse balance: value = {}, error = {:?}",
                "10000000000000000000000", e
            )
        })?;
    for line in buffered.lines() {
        let keypair =
            KeyPair::from_secret(line.unwrap().parse().unwrap()).unwrap();
        accounts.insert(keypair.address(), balance.clone());
        secret_store.insert(keypair);
    }
    Ok(accounts)
}

pub fn initialize_internal_contract_accounts(
    state: &mut dyn StateOpsTrait, contract_start_nonce: U256,
) {
    || -> DbResult<()> {
        {
            for address in InternalContractMap::new().keys() {
                state.new_contract_with_admin(
                    address,
                    /* No admin; admin = */ &Address::zero(),
                    /* balance = */ U256::zero(),
                    contract_start_nonce,
                    Some(STORAGE_LAYOUT_REGULAR_V0),
                )?;
            }
            Ok(())
        }
    }()
    .expect(&concat!(file!(), ":", line!(), ":", column!()));
}

fn genesis_contract_address_impl(idx: usize, code: &Bytes) -> Address {
    let genesis_account_address =
        GENESIS_ACCOUNT_ADDRESS_STR.parse::<Address>().unwrap();
    let (address, _) = contract_address(
        CreateContractAddress::FromSenderNonceAndCodeHash,
        0.into(),
        &genesis_account_address,
        &U256::from(idx),
        code,
    );
    address
}

pub fn genesis_contract_address_four_year() -> Address {
    genesis_contract_address_impl(
        2,
        &GENESIS_TRANSACTION_CREATE_GENESIS_TOKEN_MANAGER_FOUR_YEAR_UNLOCK
            .from_hex()
            .unwrap(),
    )
}

pub fn genesis_contract_address_two_year() -> Address {
    genesis_contract_address_impl(
        1,
        &GENESIS_TRANSACTION_CREATE_GENESIS_TOKEN_MANAGER_TWO_YEAR_UNLOCK
            .from_hex()
            .unwrap(),
    )
}

/// ` test_net_version` is used to update the genesis author so that after
/// resetting, the chain of the older version will be discarded
pub fn genesis_block(
    storage_manager: &Arc<StorageManager>,
    genesis_accounts: HashMap<Address, U256>, test_net_version: Address,
    initial_difficulty: U256, machine: Arc<Machine>, need_to_execute: bool,
    genesis_chain_id: Option<u32>,
) -> Block
{
    let mut state =
        State::new(StateDb::new(storage_manager.get_state_for_genesis_write()))
            .expect("Failed to initialize state");

    let mut genesis_block_author = test_net_version;
    genesis_block_author.set_user_account_type_bits();

    let mut total_balance = U256::from(0);
    initialize_internal_contract_accounts(
        &mut state,
        machine
            .spec(/* block_number = */ 0)
            .contract_start_nonce(/* block_number = */ 0),
    );
    for (addr, balance) in genesis_accounts {
        state
            .add_balance(
                &addr,
                &balance,
                CleanupMode::NoEmpty,
                /* account_start_nonce = */ U256::zero(),
            )
            .unwrap();
        total_balance += balance;
    }
    state.add_total_issued(total_balance);

    let genesis_account_address =
        GENESIS_ACCOUNT_ADDRESS_STR.parse::<Address>().unwrap();

    let genesis_token_count =
        U256::from(GENESIS_TOKEN_COUNT_IN_CFX) * U256::from(ONE_CFX_IN_DRIP);
    state.add_total_issued(genesis_token_count);
    let two_year_unlock_token_count =
        U256::from(TWO_YEAR_UNLOCK_TOKEN_COUNT_IN_CFX)
            * U256::from(ONE_CFX_IN_DRIP);
    let four_year_unlock_token_count =
        genesis_token_count - two_year_unlock_token_count;

    let genesis_account_init_balance =
        U256::from(ONE_CFX_IN_DRIP) * 100 + genesis_token_count;
    state
        .add_balance(
            &genesis_account_address,
            &genesis_account_init_balance,
            CleanupMode::NoEmpty,
            /* account_start_nonce = */ U256::zero(),
        )
        .unwrap();

    let mut debug_record = Some(ComputeEpochDebugRecord::default());

    let genesis_chain_id = genesis_chain_id.unwrap_or(0);
    let mut genesis_transaction = Transaction::default();
    genesis_transaction.data = GENESIS_TRANSACTION_DATA_STR.as_bytes().into();
    genesis_transaction.action = Action::Call(Default::default());
    genesis_transaction.chain_id = genesis_chain_id;

    let mut create_create2factory_transaction = Transaction::default();
    create_create2factory_transaction.nonce = 0.into();
    create_create2factory_transaction.data =
        GENESIS_TRANSACTION_CREATE_CREATE2FACTORY
            .from_hex()
            .unwrap();
    create_create2factory_transaction.action = Action::Create;
    create_create2factory_transaction.chain_id = genesis_chain_id;
    create_create2factory_transaction.gas = 300000.into();
    create_create2factory_transaction.gas_price = 1.into();
    create_create2factory_transaction.storage_limit = 512;

    let mut create_genesis_token_manager_two_year_unlock_transaction =
        Transaction::default();
    create_genesis_token_manager_two_year_unlock_transaction.nonce = 1.into();
    create_genesis_token_manager_two_year_unlock_transaction.data =
        GENESIS_TRANSACTION_CREATE_GENESIS_TOKEN_MANAGER_TWO_YEAR_UNLOCK
            .from_hex()
            .unwrap();
    create_genesis_token_manager_two_year_unlock_transaction.value =
        two_year_unlock_token_count;
    create_genesis_token_manager_two_year_unlock_transaction.action =
        Action::Create;
    create_genesis_token_manager_two_year_unlock_transaction.chain_id =
        genesis_chain_id;
    create_genesis_token_manager_two_year_unlock_transaction.gas =
        2800000.into();
    create_genesis_token_manager_two_year_unlock_transaction.gas_price =
        1.into();
    create_genesis_token_manager_two_year_unlock_transaction.storage_limit =
        16000;

    let mut create_genesis_token_manager_four_year_unlock_transaction =
        Transaction::default();
    create_genesis_token_manager_four_year_unlock_transaction.nonce = 2.into();
    create_genesis_token_manager_four_year_unlock_transaction.data =
        GENESIS_TRANSACTION_CREATE_GENESIS_TOKEN_MANAGER_FOUR_YEAR_UNLOCK
            .from_hex()
            .unwrap();
    create_genesis_token_manager_four_year_unlock_transaction.value =
        four_year_unlock_token_count;
    create_genesis_token_manager_four_year_unlock_transaction.action =
        Action::Create;
    create_genesis_token_manager_four_year_unlock_transaction.chain_id =
        genesis_chain_id;
    create_genesis_token_manager_four_year_unlock_transaction.gas =
        5000000.into();
    create_genesis_token_manager_four_year_unlock_transaction.gas_price =
        1.into();
    create_genesis_token_manager_four_year_unlock_transaction.storage_limit =
        32000;

    let mut create_genesis_investor_fund_transaction = Transaction::default();
    create_genesis_investor_fund_transaction.nonce = 3.into();
    create_genesis_investor_fund_transaction.data =
        GENESIS_TRANSACTION_CREATE_FUND_POOL.from_hex().unwrap();
    create_genesis_investor_fund_transaction.action = Action::Create;
    create_genesis_investor_fund_transaction.chain_id = genesis_chain_id;
    create_genesis_investor_fund_transaction.gas = 400000.into();
    create_genesis_investor_fund_transaction.gas_price = 1.into();
    create_genesis_investor_fund_transaction.storage_limit = 1000;

    let mut create_genesis_team_fund_transaction = Transaction::default();
    create_genesis_team_fund_transaction.nonce = 4.into();
    create_genesis_team_fund_transaction.data =
        GENESIS_TRANSACTION_CREATE_FUND_POOL.from_hex().unwrap();
    create_genesis_team_fund_transaction.action = Action::Create;
    create_genesis_team_fund_transaction.chain_id = genesis_chain_id;
    create_genesis_team_fund_transaction.gas = 400000.into();
    create_genesis_team_fund_transaction.gas_price = 1.into();
    create_genesis_team_fund_transaction.storage_limit = 1000;

    let mut create_genesis_eco_fund_transaction = Transaction::default();
    create_genesis_eco_fund_transaction.nonce = 5.into();
    create_genesis_eco_fund_transaction.data =
        GENESIS_TRANSACTION_CREATE_FUND_POOL.from_hex().unwrap();
    create_genesis_eco_fund_transaction.action = Action::Create;
    create_genesis_eco_fund_transaction.chain_id = genesis_chain_id;
    create_genesis_eco_fund_transaction.gas = 400000.into();
    create_genesis_eco_fund_transaction.gas_price = 1.into();
    create_genesis_eco_fund_transaction.storage_limit = 1000;

    let mut create_genesis_community_fund_transaction = Transaction::default();
    create_genesis_community_fund_transaction.nonce = 6.into();
    create_genesis_community_fund_transaction.data =
        GENESIS_TRANSACTION_CREATE_FUND_POOL.from_hex().unwrap();
    create_genesis_community_fund_transaction.action = Action::Create;
    create_genesis_community_fund_transaction.chain_id = genesis_chain_id;
    create_genesis_community_fund_transaction.gas = 400000.into();
    create_genesis_community_fund_transaction.gas_price = 1.into();
    create_genesis_community_fund_transaction.storage_limit = 1000;

    let genesis_transactions = vec![
        Arc::new(genesis_transaction.fake_sign(Default::default())),
        Arc::new(
            create_create2factory_transaction
                .fake_sign(genesis_account_address),
        ),
        Arc::new(
            create_genesis_token_manager_two_year_unlock_transaction
                .fake_sign(genesis_account_address),
        ),
        Arc::new(
            create_genesis_token_manager_four_year_unlock_transaction
                .fake_sign(genesis_account_address),
        ),
        Arc::new(
            create_genesis_investor_fund_transaction
                .fake_sign(genesis_account_address),
        ),
        Arc::new(
            create_genesis_team_fund_transaction
                .fake_sign(genesis_account_address),
        ),
        Arc::new(
            create_genesis_eco_fund_transaction
                .fake_sign(genesis_account_address),
        ),
        Arc::new(
            create_genesis_community_fund_transaction
                .fake_sign(genesis_account_address),
        ),
    ];

    if need_to_execute {
        const CREATE2FACTORY_TX_INDEX: usize = 1;
        /*
        const TWO_YEAR_UNLOCK_TX_INDEX: usize = 2;
        const FOUR_YEAR_UNLOCK_TX_INDEX: usize = 3;
        const INVESTOR_FUND_TX_INDEX: usize = 4;
        const TEAM_FUND_TX_INDEX: usize = 5;
        const ECO_FUND_TX_INDEX: usize = 6;
        const COMMUNITY_FUND_TX_INDEX: usize = 7;
        */
        let contract_name_list = vec![
            "CREATE2FACTORY",
            "TWO_YEAR_UNLOCK",
            "FOUR_YEAR_UNLOCK",
            "INVESTOR_FUND",
            "TEAM_FUND",
            "ECO_FUND",
            "COMMUNITY_FUND",
        ];

        for i in CREATE2FACTORY_TX_INDEX..=contract_name_list.len() {
            execute_genesis_transaction(
                genesis_transactions[i].as_ref(),
                &mut state,
                machine.clone(),
            );

            let (contract_address, _) = contract_address(
                CreateContractAddress::FromSenderNonceAndCodeHash,
                0.into(),
                &genesis_account_address,
                &(i - 1).into(),
                &genesis_transactions[i].as_ref().data,
            );

            state
                .set_admin(&contract_address, &Address::zero())
                .expect("");
            info!(
                "Genesis {:?} addresses: {:?}",
                contract_name_list[i - 1],
                contract_address
            );
        }
    }

    state
        .clean_account(&genesis_account_address)
        .expect("Clean account failed");

    let state_root = state
        .compute_state_root(/* debug_record = */ debug_record.as_mut())
        .unwrap();
    let receipt_root = compute_receipts_root(&vec![Arc::new(BlockReceipts {
        receipts: vec![],
        block_number: 0,
        secondary_reward: U256::zero(),
        tx_execution_error_messages: vec![],
    })]);

    let mut genesis = Block::new(
        BlockHeaderBuilder::new()
            .with_deferred_state_root(state_root.aux_info.state_root_hash)
            .with_deferred_receipts_root(receipt_root)
            .with_gas_limit(GENESIS_GAS_LIMIT.into())
            .with_author(genesis_block_author)
            .with_difficulty(initial_difficulty)
            .with_transactions_root(compute_transaction_root(
                &genesis_transactions,
            ))
            .build(),
        genesis_transactions,
    );
    genesis.block_header.compute_hash();
    debug!(
        "Initialize genesis_block={:?} hash={:?}",
        genesis,
        genesis.hash()
    );

    state
        .commit(
            genesis.block_header.hash(),
            /* debug_record = */ debug_record.as_mut(),
        )
        .unwrap();
    genesis.block_header.pow_hash = Some(Default::default());
    debug!(
        "genesis debug_record {}",
        serde_json::to_string(&debug_record).unwrap()
    );
    genesis
}

fn execute_genesis_transaction(
    transaction: &SignedTransaction, state: &mut State, machine: Arc<Machine>,
) {
    let env = Env::default();
    let internal_contract_map = InternalContractMap::new();

    let options = TransactOptions::with_no_tracing();
    let r = {
        Executive::new(
            state,
            &env,
            machine.as_ref(),
            &machine.spec(env.number),
            &internal_contract_map,
        )
        .transact(transaction, options)
        .unwrap()
    };

    match &r {
        ExecutionOutcome::Finished(_executed) => {}
        _ => {
            panic!("genesis transaction should not fail! err={:?}", r);
        }
    }
}

pub fn load_file(
    path: &String, address_parser: impl Fn(&str) -> Result<Address, String>,
) -> Result<HashMap<Address, U256>, String> {
    let mut content = String::new();
    let mut file = File::open(path)
        .map_err(|e| format!("failed to open file: {:?}", e))?;
    file.read_to_string(&mut content)
        .map_err(|e| format!("failed to read file content: {:?}", e))?;
    let account_values = content
        .parse::<toml::Value>()
        .map_err(|e| format!("failed to parse toml file: {:?}", e))?;

    let mut accounts: HashMap<Address, U256> = HashMap::new();
    match account_values {
        Value::Table(table) => {
            for (key, value) in table {
                let addr = address_parser(&key).map_err(|e| {
                    format!(
                        "failed to parse address: value = {}, error = {:?}",
                        key, e
                    )
                })?;

                match value {
                    Value::String(balance) => {
                        let balance = U256::from_dec_str(&balance).map_err(|e| format!("failed to parse balance: value = {}, error = {:?}", balance, e))?;
                        accounts.insert(addr, balance);
                    }
                    _ => {
                        return Err(
                            "balance in toml file requires String type".into(),
                        );
                    }
                }
            }
        }
        _ => {
            return Err(format!(
                "invalid root value type {:?} in toml file",
                account_values.type_str()
            ));
        }
    }

    Ok(accounts)
}
